/** check_the functions in the 'Common' dir.
 * See: http://check.sourceforge.net/doc/check_html/check_3.html#SEC4
 */
#include <stdlib.h>
#include <check.h>
#include "../include/netops.h"

#include <sys/types.h>
// defines sock_stream
#include <sys/socket.h>

// define strlen().
#include <string.h>

// for printf.
//#include <stdio.h>


/**
 * The command msg size, is the size of the message used for commands and status exchange
 *   between the agents and sub-agents.
 *
 *   e.g.
 *    go:Spawn, go:Init, go:Execute, go:Stop, go:ClearDown
 *    done:Spawn, ...
 *    FAILED:Spawn, ...
 *
 *    So right now 50 looks like a good number, I've seen messages of 37 chars.
 *    The Time stamp alone is 22 chars. and that needs to go in there twice.
 */
#define CMD_MESSAGE_SIZE 200

/// This is payload size of the config commmand message. So it must be lower than CMD_MESSAGE_SIZE. (-7 for 'config:'
#define CMD_MSG_PAYLOAD_SIZE CMD_MESSAGE_SIZE - 7



int AllocateIpMessage(int bBind, int nPort, const char *szAddress,
		int nMsgType, struct sockaddr_in *pstReturnSin);

START_TEST( test_AllocateIpMessage) {
	// the 1 indicates that bind should be called.
	int nHandle = AllocateIpMessage(1, 1487, "0.0.0.0", SOCK_STREAM, NULL);
	fail_unless(nHandle != -1, "Failed to CreateTcpMessage().");
	ReleaseIpMessage(nHandle);
}
END_TEST

START_TEST( test_CreateUdpMessage) {
	int nHandle = CreateUdpMessage(1487);
	fail_unless(nHandle != -1, "Failed to CreateUdpMessage().");
	CloseSocket(nHandle);
}
END_TEST

START_TEST( test_CreateTcpMessage) {
	int nHandle = CreateTcpMessage(1487);
	fail_unless(nHandle != -1, "Failed to CreateTcpMessage().");
	CloseSocket(nHandle);
}
END_TEST

START_TEST( test_DestroyTcpMessage) {
	int nRc = CloseSocket(1487);
	fail_unless(nRc == -1,
			"Didn't detect that it is closing a non-existing socket. DestroyTcpMessage()");

	int nHandle = CreateTcpMessage(1487);
	nRc = CloseSocket(nHandle);
	fail_unless(nRc == 0, "Failed to close open socket. DestroyTcpMessage().");
}
END_TEST

START_TEST( test_OpenTcpMessage) {
	int nPort = 1487;
	char szIpAddress[] = "127.0.0.1";

	//puts("should pass");
	int nServerHandle = CreateTcpMessage(nPort);
	int nClientHandle = OpenTcpMessage(nPort, szIpAddress);
	fail_unless(nClientHandle != -1, "Failed to OpenTcpMessage().");
	CloseSocket(nClientHandle);

	//puts("should fail");
	// This should fail.
	nClientHandle = OpenTcpMessage(1388, szIpAddress);
	fail_unless(
			nClientHandle == -1,
			"Failed OpenTcpMessage() didn't return an error when connected to a non existing IP address.");
	CloseSocket(nServerHandle);
}
END_TEST

//
// ReceiveUdpMessage(int nSockDescriptor, char *szMessage, int nMaxMessageLength, int nRecoverOnIntr
START_TEST( test_SendAndReceiveUdp) {
	int nPort = 1487;
	char szIpDotAddress[] = "127.0.0.1";
	struct sockaddr_in stSockAddr;
	char szSendMessage[] = "Hello Doctor Falcon";
	char szRecvMessage[50];
	int nRecoverOnIntr = 0;

	//puts("should pass");
	int nServerHandle = CreateUdpMessage(nPort);
	fail_unless(nServerHandle != -1, "Failed to CreateUdpMessages().");

	int nClientHandle = OpenUdpMessage(szIpDotAddress, nPort, &stSockAddr);
	fail_unless(nClientHandle != -1, "Failed to OpenUdpMessage().");

	// The +1 to strlen is to include the \0.
	ssize_t nBytesSend = SendUdpMessage(&stSockAddr, nClientHandle, szSendMessage, strlen(
			szSendMessage) + 1);
	fail_unless(nBytesSend != -1, "Failed to SendUdpMessage().");
	nBytesSend = SendUdpMessage(&stSockAddr, nClientHandle, szSendMessage, strlen(
			szSendMessage) + 1);
	fail_unless(nBytesSend != -1, "Failed to SendUdpMessage().");

	ssize_t nBytesRecv = ReceiveUdpMessage(nServerHandle, szRecvMessage,
			sizeof(szRecvMessage), nRecoverOnIntr);
	fail_unless(nBytesRecv != -1, "Failed to ReceiveUdpMessage().");
	//printf("   test_SendAndReceive() Received message: %s\n", szRecvMessage);

	nBytesRecv = ReceiveUdpMessage(nServerHandle, szRecvMessage,
			sizeof(szRecvMessage), nRecoverOnIntr);
	fail_unless(nBytesRecv != -1, "Failed to ReceiveUdpMessage().");
	//printf("   test_SendAndReceive() Received message: %s\n", szRecvMessage);

	CloseSocket(nClientHandle);
	CloseSocket(nServerHandle);
}
END_TEST



Suite *netops_suite(void) {
	Suite *s = suite_create("NetOps");

	/* Core test case */
	TCase *tc_core = tcase_create("Core");
	tcase_add_test(tc_core, test_AllocateIpMessage);
	tcase_add_test(tc_core, test_CreateTcpMessage);
	tcase_add_test(tc_core, test_CreateUdpMessage);
	tcase_add_test(tc_core, test_DestroyTcpMessage);
	tcase_add_test(tc_core, test_OpenTcpMessage);
	tcase_add_test(tc_core, test_SendAndReceiveUdp);
	suite_add_tcase(s, tc_core);

	/* Limits test case
	 TCase *tc_limits = tcase_create ("Limits");
	 tcase_add_test (tc_limits, test_money_create_neg);
	 tcase_add_test (tc_limits, test_money_create_zero);
	 suite_add_tcase (s, tc_limits);
	 */
	return s;
}

